package com.mijie.homi.test;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.wltea.analyzer.lucene.IKAnalyzer;
import org.wltea.analyzer.lucene.NatureAttribute;

public class TopicExtractor {

	private static IKAnalyzer analyzer = new IKAnalyzer(true);
	private GrammarLoader grammar = new GrammarLoader();
	
	public static void main(String[] args) throws IOException{
		String line1 = "大多数的我们都拥有着美好的初恋，可是到最后，大多数的彼此却不得不分开，有些时候是因为不爱了，有些时候是因为横亘在彼此面前的现实因素，你是否还记得你初恋时青涩的样子";
		String line2 = "据说很多男人都喜欢很瘦的女人。。我曾经也很喜欢。。但是今天我不喜欢了";
		String line3 = "清晨睁开眼，我们就要对自己说：“今天是最好的一天！”不管昨天发生了什么，都已成为过去，无法改变。不要让昨天的烦恼影响到今天的好心情！开始一天的工作时，不管有多忙碌，压力有多大，都不要抱怨,不要因此影响了我们的心情。哭，也是一天；笑，也是一天，何不让我们怀着最美的心情过好每一天呢？";
		String line4 = "最近小学同学准备搞聚会，然后某个同学建了个小学同学群。因为以前我们读小学的时候，也不会上网了，那时候连电脑都比较少来吧。";
		String line5 = "嗯嗯，只要我们勇敢面对，无论多大的坎都会过去的，谢谢你的开导，让我们共同为美好的未来，一起加油吧";
		String line6 = "一些盗版制品经营者为了应付和躲避打击，经营手法更为隐蔽。";
		String[] lines = {line1,line2,line3,line4,line5,line6};
		TopicExtractor extractor = new TopicExtractor();
		for(String line : lines){
			System.out.println(line);
			Term term = extractor.getTerms(line);
			do{
				System.out.print(term.text+"["+term.startOffset+","+term.endOffset+"]/"+term.natureString()+" ");
			}while((term=term.next)!=null);
			System.out.println();
			
			
			String[] entry = line.split(",|，|\\.|。|\\?|？|!|！");
			StringBuilder sb = new StringBuilder();
			for(String e : entry){
				if(e.trim().isEmpty()) continue;
				List<Word> list = extractor.extract(e);
				if(!list.isEmpty()){
					for(Word w : list){
						sb.append(w.text);
					}
					sb.append(",");
				}
			}
			System.out.println("extract topic:"+sb.toString());
		}
		
	}
	
	public TopicExtractor(){
		try {
			grammar.init();
		} catch (IOException e) {
			grammar = null;
		}
	}
	
	public List<Word> extract(String line) throws IOException{
		List<Word> list = new ArrayList<Word>();
		Term term = getTerms(line);
		NatureNode node = null;
		String prevNature = null;
		Term single = null;
		do{
			single = null;
			for(String nature : term.natures){
				node = grammar.getTree(nature);
				if(node==null) continue;
				if(term.next==null){
					if(node.isLeaf())
						list.add(new Word(term.text));
					break;
				}
				if(node.isLeaf()) single = term;
				
				node = findNextNatureNode(prevNature,term.next,node);
				if(node!=null){
					single = null;
					int step = countNode(node);
					for(int i=0;i<step;i++){
						list.add(new Word(term.text));
						term = term.next;
						if(term==null) return list;
					}
					term = term.prev;
					break;
				}
				prevNature = nature;
			}
			
			if(single!=null) list.add(new Word(single.text));
		}while((term=term.next)!=null);
		return list;
	}
	
	private int countNode(NatureNode node){
		if(node==null) return 0;
		int count = 1;
		return count += countNode(node.prev());
		
	}
	
	private NatureNode findNextNatureNode(String prevNature,Term term,NatureNode node){
		if(node==null) return null;
		NatureNode child = null;
		String lastNature = null;
		for(String nature : term.natures){
			child = node.findChild(nature);
			lastNature = nature;
			if(child!=null){
				if(term.next==null){
					if(!(child.name().equals(nature) && child.isLeaf())){
						child = null;
					}
					break;
				}
				return findNextNatureNode(lastNature,term.next,child);
			}else{
				if(node.name().equals(prevNature) && node.isLeaf()){
					return node;
				}
			}
		}
		return child;
	}
	
	
	
	
	
	private Term getTerms(String str) throws IOException {
		StringReader reader = new StringReader(str); 
		TokenStream ts = analyzer.tokenStream(str, reader);
		ts.reset();
		CharTermAttribute termAtt = ts.getAttribute(CharTermAttribute.class);
		NatureAttribute nature = ts.getAttribute(NatureAttribute.class);
		OffsetAttribute offset = ts.getAttribute(OffsetAttribute.class);
		
	    Term root = null;
		try {
			Term prev = null;
			Term curr = null;
			while (ts.incrementToken()){
				if(root==null){
					root = new Term(termAtt.toString(),offset.startOffset(),offset.endOffset());
					curr = root;
					prev = root;
				}else{
					prev.next = new Term(termAtt.toString(),offset.startOffset(),offset.endOffset());
					curr = prev.next;
					curr.prev = prev;
				}
				if(nature.natures()!=null){
					for(String s : nature.natures()){
						curr.addNature(s);
					}
				}
				
				if(curr.isNature("o") || curr.isNature("y") ||
					curr.isNature("nd") || curr.isNature("mq"))
					continue;

				prev = curr;
			 }
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		return root;
	}
	
	class Word{
		String text;
		Word next;
		Word prev;

		Word(String text){
			this.text = text;
		}
	}
	
	class Term{
		String text;
		int startOffset;
		int endOffset;
		Term next;
		Term prev;
		private Set<String> natures = new HashSet<String>();
		
		Term(String text, int startOffset, int endOffset) {
			this.text = text;
			this.startOffset = startOffset;
			this.endOffset = endOffset;
		}
		
		int length(){
			return text.length();
		}
		
		void addNature(String n){
			natures.add(n);
		}
		
		boolean isNature(String n){
			return natures.contains(n);
		}
		
		int natureSize(){
			return natures.size();
		}
		
		public String natureString(){
			StringBuilder sb = new StringBuilder();
			if(!natures.isEmpty()){
				for(String n : natures){
					sb.append(n).append(",");
				}
				sb.deleteCharAt(sb.length()-1);
			}
			return sb.toString();
		}

		@Override
		public String toString() {
			StringBuilder sb = new StringBuilder();
			sb.append(text).append("/");
			for(String n : natures){
				sb.append(n).append(",");
			}
			sb.deleteCharAt(sb.length()-1);
			return sb.toString();
		}
		
	}
}
